package com.tbl.modules.wms.service.Impl.move;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.tbl.common.utils.DateUtils;
import com.tbl.common.utils.PageTbl;
import com.tbl.common.utils.PageUtils;
import com.tbl.common.utils.StringUtils;
import com.tbl.modules.wms.constant.Constant;
import com.tbl.modules.wms.dao.baseinfo.CarDAO;
import com.tbl.modules.wms.dao.baseinfo.FactoryAreaDAO;
import com.tbl.modules.wms.dao.baseinfo.ShelfDAO;
import com.tbl.modules.wms.dao.baseinfo.WarehouseDAO;
import com.tbl.modules.wms.dao.instorage.InstorageDetailDAO;
import com.tbl.modules.wms.dao.move.MoveInStorageDAO;
import com.tbl.modules.wms.dao.move.MoveOutStorageDAO;
import com.tbl.modules.wms.dao.move.MoveStorageDAO;
import com.tbl.modules.wms.dao.move.MoveStorageDetailDAO;
import com.tbl.modules.wms.dao.pda.RfidBindDAO;
import com.tbl.modules.wms.dao.storageinfo.StorageInfoDAO;
import com.tbl.modules.wms.entity.baseinfo.Car;
import com.tbl.modules.wms.entity.baseinfo.FactoryArea;
import com.tbl.modules.wms.entity.baseinfo.Shelf;
import com.tbl.modules.wms.entity.baseinfo.Warehouse;
import com.tbl.modules.wms.entity.instorage.InstorageDetail;
import com.tbl.modules.wms.entity.move.MoveInStorage;
import com.tbl.modules.wms.entity.move.MoveOutStorage;
import com.tbl.modules.wms.entity.move.MoveStorage;
import com.tbl.modules.wms.entity.move.MoveStorageDetail;
import com.tbl.modules.wms.entity.storageinfo.StorageInfo;
import com.tbl.modules.wms.service.Impl.baseinfo.ShelfServiceImpl;
import com.tbl.modules.wms.service.Impl.interfaceLog.InterfaceDoServiceImpl;
import com.tbl.modules.wms.service.move.MoveStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 移库管理
 * @author 70486
 */
@Service
public class MoveStorageServiceImpl extends ServiceImpl<MoveStorageDAO, MoveStorage> implements MoveStorageService {

    /**
     * 移库处理
     */
    @Autowired
    private MoveStorageDAO moveStorageDAO;
    /**
     * 移库处理详情
     */
    @Autowired
    private MoveStorageDetailDAO moveStorageDetailDAO;
    /**
     * 库存
     */
    @Autowired
    private StorageInfoDAO storageInfoDAO;
    /**
     * 仓库
     */
    @Autowired
    private WarehouseDAO warehouseDAO;
    /**
     * 行车
     */
    @Autowired
    private CarDAO carDAO;
    /**
     * 库位
     */
    @Autowired
    private ShelfDAO shelfDAO;
    /**
     * 移库入库
     */
    @Autowired
    private MoveInStorageDAO moveInStorageDAO;
    /**
     * 移库出库
     */
    @Autowired
    private MoveOutStorageDAO moveOutStorageDAO;
    /**
     * 接口执行
     */
    @Autowired
    private InterfaceDoServiceImpl interfaceDoServiceImpl;
    /**
     * rfid绑定表
     */
    @Autowired
    private RfidBindDAO rfidBindDAO;
    /**
     * 厂区
     */
    @Autowired
    private FactoryAreaDAO factoryAreaDAO;
    /**
     * 入库管理-订单详情
     */
    @Autowired
    private InstorageDetailDAO instorageDetailDAO;
    /**
     * 库位服务类
     */
    @Autowired
    private ShelfServiceImpl shelfImpl;

    
    /**
     * 移库单列表页数据
     * @param pageTbl
     * @param map
     * @return PageUtils
     */
    @Override
    public PageUtils getPageList(PageTbl pageTbl, Map<String, Object> map) {
        String sortName = pageTbl.getSortname();
        String sortOrder = pageTbl.getSortorder();

        if (StringUtils.isEmptyString(sortName)||"startOutTime".equals(sortName) ||"endInTime".equals(sortName) ||"moveState".equals(sortName)
                ||"state".equals(sortName)) {
        	sortName = "t1.id";
        }

        if(map.get("warehouse")!=null&&!"".equals(map.get("warehouse"))){
        	map.put("warehouseCode", warehouseDAO.selectById(Long.valueOf((String) map.get("warehouse"))).getCode());
        }
        if (StringUtils.isEmptyString(sortOrder)) {
            sortOrder = "desc";
        }
       
        Page page = new Page(pageTbl.getPageno(), pageTbl.getPagesize(), sortName, "asc".equalsIgnoreCase(sortOrder));
        return new PageUtils(page.setRecords(moveStorageDAO.getPageList(page, map)));
    }

    /**
     * 根据主键获取到详情的列表
     * @param pageTbl
     * @param id 移库明细主键
     * @return PageUtils
     */
    @Override
    public PageUtils getPageDetailList(PageTbl pageTbl, Integer id) {
        String sortName = pageTbl.getSortname();
        String sortOrder = pageTbl.getSortorder();
        if (StringUtils.isEmptyString(sortName) || "cz".equalsIgnoreCase(sortName)) {
            sortName = "id";
        }
        if (StringUtils.isEmptyString(sortOrder)) {
            sortOrder = "desc";
        }
        Page page = new Page(pageTbl.getPageno(), pageTbl.getPagesize(), sortName, "asc".equalsIgnoreCase(sortOrder));
        return new PageUtils(page.setRecords(moveStorageDAO.getDetailList(page, id)));
    }

    /**
     * 点击查看，获取详情列表页数据
     * @param id 移库单主键
     * @return MoveStorage 移库单
     */
    @Override
    public MoveStorage selectInfoById(Long id) {
        return moveStorageDAO.selectInfoById(id);
    }

    /**
     * 获得导出Excel列表数据
     * @param map
     * @return List<MoveStorage>
     */
    @Override
    public List<MoveStorage> getExcelList(Map<String, Object> map) {
        List<MoveStorage> lstMoveStorage = moveStorageDAO.getExcelList(map);
        lstMoveStorage.forEach(moveStorage -> {
            if (moveStorage.getMoveState().contains(Constant.STRING_TWO)||moveStorage.getMoveState().contains(Constant.STRING_THREE)
                    ||moveStorage.getMoveState().contains(Constant.STRING_FOUR)){
                moveStorage.setMoveState("移库中");
            }else if (moveStorage.getMoveState().contains(Constant.STRING_ONE)){
                if (moveStorage.getMoveState().contains(Constant.STRING_FIVE)){
                    moveStorage.setMoveState("移库中");
                }else{
                    moveStorage.setMoveState("新建");
                }
            }else if (moveStorage.getMoveState().contains(Constant.STRING_FIVE)){
                moveStorage.setMoveState("完成");
            }else{
                moveStorage.setMoveState("其他");
            }
        });
        return lstMoveStorage;
    }

    /**
     * 点击保存，保存主表信息
     * @param moveStorage 移库单
     * @return Long 移库单主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveMoveStorage(MoveStorage moveStorage) {
        if (moveStorage.getId() == -1) {
            String serial = new DecimalFormat("0000").format(moveStorageDAO.selectLatestAllocation() + 1);
            Warehouse warehouse = warehouseDAO.selectById(moveStorage.getWarehouseId());
            moveStorage.setMoveCode("YK" + DateUtils.longToString2(System.currentTimeMillis()) + serial);
            moveStorage.setMoveTime(new Date());
            moveStorage.setWarehouseCode(warehouse.getCode());
            this.insert(moveStorage);
            moveStorageDAO.updateSerial(serial,"move");
        }
        return moveStorage.getId();
    }

    /**
     * 编辑页面点击提交，修改状态
     * @param moveStorage 移库单
     * @return Map<String,Object>
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> subMoveStorage(MoveStorage moveStorage) {
        Map<String, Object> map = new HashMap<>(2);
        List<MoveStorageDetail> lstMoveStorageDetail = moveStorageDetailDAO.selectByMap(new HashMap<String, Object>(1) {{
            put("PID", moveStorage.getId());
        }});
        if (lstMoveStorageDetail == null || lstMoveStorageDetail.size() == 0) {
            map.put("result", false);
            map.put("msg", "请选择质保单号!");
            return map;
        }
        Warehouse warehouse = warehouseDAO.selectById(moveStorage.getWarehouseId());
        moveStorage.setState(2);
        moveStorage.setWarehouseCode(warehouse.getCode());
        this.insertOrUpdate(moveStorage);
        lstMoveStorageDetail.forEach(a -> {
            a.setWarehouseCode(warehouse.getCode());
            moveStorageDetailDAO.updateById(a);
        });
        map.put("result", true);
        map.put("msg", "提交成功");
        return map;
    }
    
    /**
     * 新增页面点击提交，修改状态
     * @param moveStorage 移库单
     * @return Map<String,Object>
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> subMoveStorage2(MoveStorage moveStorage) {
        Map<String, Object> map = new HashMap<>();
        List<MoveStorageDetail> lstMoveStorageDetail = moveStorageDetailDAO.selectByMap(new HashMap<String, Object>() {{
            put("PID", moveStorage.getId());
        }});
        if (lstMoveStorageDetail == null || lstMoveStorageDetail.size() == 0) {
            map.put("result", false);
            map.put("msg", "请选择质保单号!");
            return map;
        }
        Warehouse warehouse = warehouseDAO.selectById(moveStorage.getWarehouseId());
        FactoryArea factoryArea = factoryAreaDAO.selectById(moveStorage.getFactoryCode());
        moveStorage.setState(2);
        moveStorage.setWarehouseCode(warehouse.getCode());
        moveStorage.setFactoryCode(factoryArea.getCode());
        this.insertOrUpdate(moveStorage);
        lstMoveStorageDetail.forEach(a -> {
            a.setWarehouseCode(warehouse.getCode());
            moveStorageDetailDAO.updateById(a);
        });
        map.put("result", true);
        map.put("msg", "提交成功");
        return map;
    }

    /**
     * 获取质保单号列表
     * @param pageTbl
     * @param map
     * @return PageUtils
     */
    @Override
    public PageUtils getQaCode(PageTbl pageTbl, Map<String, Object> map) {
        Page<Map<String, Object>> page = new Page<>(pageTbl.getPageno(), pageTbl.getPagesize());
        return new PageUtils(page.setRecords(moveStorageDAO.getQaCode(page, map)));
    }

    /**
     * 移库单管理详情添加
     * @param id 移库单主键
     * @param qaCodeIds 库存主键
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveMoveStorageDetail(Long id, String[] qaCodeIds) {
        List<Long> idList = StringUtils.toLongList(qaCodeIds);
        if (idList!=null) {
            idList.forEach(a -> {
                StorageInfo storageInfo = storageInfoDAO.selectById(a);
                MoveStorage moveStorage = moveStorageDAO.selectById(id);
                MoveStorageDetail moveStorageDetail = new MoveStorageDetail();
                moveStorageDetail.setMaterialCode(storageInfo.getMaterialCode());
                moveStorageDetail.setMeter(storageInfo.getMeter());
                moveStorageDetail.setQaCode(storageInfo.getQaCode());
                moveStorageDetail.setRfid(storageInfo.getRfid());
                moveStorageDetail.setPId(id);
                moveStorageDetail.setQaCode(storageInfo.getQaCode());
                moveStorageDetail.setBatchNo(storageInfo.getBatchNo());
                moveStorageDetail.setOrg(storageInfo.getOrg());
                moveStorageDetail.setOutShelfCode(storageInfo.getShelfCode());
                moveStorageDetail.setWarehouseCode(moveStorage.getWarehouseCode());
                moveStorageDetail.setOrg(moveStorage.getFactoryCode());
                moveStorageDetail.setDishnumber(storageInfo.getDishnumber());
                moveStorageDetailDAO.insert(moveStorageDetail);

                storageInfo.setState(2);
                storageInfoDAO.updateById(storageInfo);
            });
        }

        return true;
    }

    /**
     * 删除明细数据
     * @param ids 移库详情主键
     * @return Map<String,Object>
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> deleteMoveStorageDetailIds(String[] ids) {
        Map<String, Object> map = new HashMap<>();
        AtomicBoolean result = new AtomicBoolean(true);
        List<Long> idList = StringUtils.toLongList(ids);
        List<Long> moveStorageDetailStateList = moveStorageDetailDAO.getStatesByMoveStorageId(idList);
        if (moveStorageDetailStateList.contains(Constant.INT_TWO) || moveStorageDetailStateList.contains(Constant.INT_THREE)
                || moveStorageDetailStateList.contains(Constant.INT_FOUR) || moveStorageDetailStateList.contains(Constant.INT_FIVE)){
            map.put("msg", "已经开始出入库流程，请勿删除！");
            map.put("result", result.get());
            return map;
        }

        //删除数据前，需要在库存表解冻该条物料
        List<String> lstMovestorageDetailQacodes = moveStorageDetailDAO.getQacodesByMoveStorageId(idList);
        StorageInfo storageInfoEntity = new StorageInfo();
        storageInfoEntity.setState(Constant.INT_ONE);
        if (lstMovestorageDetailQacodes!=null && lstMovestorageDetailQacodes.size()>0){
            storageInfoDAO.update(storageInfoEntity,new EntityWrapper<StorageInfo>().in("QACODE", lstMovestorageDetailQacodes));
        }

        result.set(moveStorageDetailDAO.deleteBatchIds(idList)>0);
        map.put("msg", result.get()?"删除成功！":"删除失败！");
        map.put("result", result.get());
        return map;
    }

    /**
     * 列表页面点击删除，删除主表和详情的数据
     * @param ids 移库单主键
     * @return Map<String,Object>
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> deleteByIds(String[] ids) {
        List<Long> infoIdList = StringUtils.toLongList(ids);
        List<String> lstQaCode = moveStorageDetailDAO.getQacodesByMoveStorageId(infoIdList);

        //更新库存的状态为 正常
        if (lstQaCode!=null && lstQaCode.size()>0){
            StorageInfo storageInfoEntity = new StorageInfo();
            storageInfoEntity.setState(1);
            storageInfoDAO.update(storageInfoEntity, new EntityWrapper<StorageInfo>().in("QACODE", lstQaCode));
        }

        Map<String, Object> map = new HashMap<>();

        if (moveStorageDAO.selectDetailsState(infoIdList) > 0) {
            map.put("msg", "该移库单已经开始进行出库入库操作，请勿删除!");
            map.put("result", false);
            return map;
        }

        moveStorageDetailDAO.delete(new EntityWrapper<MoveStorageDetail>().in("PID", infoIdList));
        moveStorageDAO.deleteBatchIds(infoIdList);
        map.put("msg", "删除成功！");
        map.put("result", true);
        return map;
    }

    /**
     * 获取调入仓库数据
     * @param pageTbl
     * @param map
     * @return PageUtils
     */
    @Override
    public PageUtils selectWarehouse(PageTbl pageTbl, Map<String, Object> map) {
        String sortName = pageTbl.getSortname();
        String sortOrder = pageTbl.getSortorder();
        if (StringUtils.isEmptyString(sortName)) {
            sortName = "id";
        }
        if (StringUtils.isEmptyString(sortOrder)) {
            sortOrder = "desc";
        }
        Page page = new Page(pageTbl.getPageno(), pageTbl.getPagesize(), sortName, "asc".equalsIgnoreCase(sortOrder));
        return new PageUtils(page.setRecords(moveStorageDAO.selectWarehouse(page, map)));
    }

    /**
     * 获取绑定行车列表
     * @param warehouseCode 仓库编码
     * @param factoryList 厂区编码
     * @return List<Car> 行车下拉框中的选择
     */
    @Override
    public List<Car> selectCarListByWarehouseCode(String warehouseCode,List<String> factoryList) {
        return moveStorageDAO.selectCarListByWarehouseCode(warehouseCode,factoryList);
    }

    /**
     * 保存行车
     * @param moveStorageDetail 移库单明细
     * @return boolean
     */
    @Override
    public boolean saveCar(MoveStorageDetail moveStorageDetail) {
        Car car = carDAO.selectById(moveStorageDetail.getCarId());
        moveStorageDetail.setOutCarCode(car.getCode());
        moveStorageDetailDAO.updateById(moveStorageDetail);
        return true;
    }

    /**
     * 开始拣货
     * @param id 移库单明细主键
     * @return boolean
     */
    @Override
    public boolean detailStart(Long id) {
        MoveStorageDetail moveStorageDetail = moveStorageDetailDAO.selectById(id);
        //状态 1:未开始 2.开始移库出库 3.完成移库出库 4.开始移库入库 5.完成移库入库
        moveStorageDetail.setState(2);
        //加拣货时间
        moveStorageDetail.setStartOutStorageTime(new Date());
        Car car = carDAO.selectOne(new Car() {{
        	setCode(moveStorageDetail.getOutCarCode());
        }});
        if(car!=null) {
        	car.setState(1L);
        	carDAO.updateById(car);
        }
        return moveStorageDetailDAO.updateById(moveStorageDetail)>0;
    }

    /**
     * 拣货完成
     * @param id 移库单明细主键
     * @param userId 用户主键
     * @return boolean 执行成功/失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean detailSuccess(Long id, Long userId) {
        MoveStorageDetail moveStorageDetail = moveStorageDetailDAO.selectById(id);
        storageInfoDAO.deleteByMap(new HashMap<String, Object>() {{
            put("QACODE", moveStorageDetail.getQaCode());
        }});

        MoveOutStorage moveOutStorage = new MoveOutStorage();
        moveOutStorage.setBatchNo(moveStorageDetail.getBatchNo());
        moveOutStorage.setMaterialCode(moveStorageDetail.getMaterialCode());
        moveOutStorage.setBatchNo(moveStorageDetail.getBatchNo());
        moveOutStorage.setQaCode(moveStorageDetail.getQaCode());
        moveOutStorage.setRfid(moveStorageDetail.getRfid());
        moveOutStorage.setMeter(moveStorageDetail.getMeter());
        moveOutStorage.setCarCode(moveStorageDetail.getOutCarCode());
        moveOutStorage.setOrg(moveStorageDetail.getOrg());
        moveOutStorage.setShelfCode(moveStorageDetail.getOutShelfCode());
        moveOutStorage.setWarehouseCode(moveStorageDetail.getWarehouseCode());
        moveOutStorage.setDishnumber(moveStorageDetail.getDishnumber());
        moveOutStorageDAO.insert(moveOutStorage);

        //状态 1:未开始 2.开始移库出库 3.完成移库出库 4.开始移库入库 5.完成移库入库
        moveStorageDetail.setState(Constant.INT_THREE);
        //加拣货人id
        moveStorageDetail.setOutStorageId(userId);
        moveStorageDetail.setStartOutStorageTime(new Date());
        moveStorageDetail.setOutstoragetime(new Date());

        carDAO.updateCarByCode(moveStorageDetail.getOutCarCode(), "", Constant.LONG_TWO);

        MoveStorage moveStorage = moveStorageDAO.selectById(moveStorageDetail.getPId());
        //库位可用
        shelfImpl.setShelfState(moveStorageDetail.getOutShelfCode(),moveStorage.getFactoryCode(),moveStorage.getWarehouseCode(),Constant.INT_ONE);

        return moveStorageDetailDAO.updateById(moveStorageDetail)>0;
    }

    /**
     * 移库入库获取列表数据
     * @param pageTbl
     * @param map
     * @return PageUtils
     */
    @Override
    public PageUtils getInDetailList(PageTbl pageTbl, Map<String, Object> map) {
        String sortName = pageTbl.getSortname();
        String sortOrder = pageTbl.getSortorder();
        if (StringUtils.isEmptyString(sortName) || "cz".equalsIgnoreCase(sortName)) {
            sortName = "t1.id";
        } else if("state".equals(sortName)) {
            sortName = "t1.state";
        }
        if (StringUtils.isEmptyString(sortOrder)) {
            sortOrder = "desc";
        }
        if (map.get("createTime") != null && !"".equals(map.get("createTime"))) {
            map.put("startTime", map.get("createTime") + " 00:00:00");
        }
        if (map.get("endTime") != null && !"".equals(map.get("endTime"))) {
            map.put("endTime", map.get("endTime") + " 23:59:59");
        }
        Page page = new Page(pageTbl.getPageno(), pageTbl.getPagesize(), sortName, "asc".equalsIgnoreCase(sortOrder));
        return new PageUtils(page.setRecords(moveStorageDAO.getInDetailList(page, map)));
    }

    /**
     * 根据主键查询移库入库明细数据
     * @param id 移库单明细主键
     * @return MoveStorageDetail 移库单明细
     */
    @Override
    public MoveStorageDetail getDetailById(Long id) {
        return moveStorageDAO.getDetailById(id);
    }

    /**
     * 获得仓库列表
     * @param factoryCode 厂区编码
     * @return List<Warehouse> 仓库列表
     */
    @Override
    public List<Warehouse> getWarehouseList(String factoryCode) {
        return moveStorageDAO.getWarehouseList(factoryCode);
    }

    /**
     * 获得行车列表
     * @param warehouseId 仓库主键
     * @return List<Car> 行车列表
     */
    @Override
    public List<Car> getCarList(Long warehouseId) {
        return moveStorageDAO.getCarList(warehouseId);
    }

    /**
     * 移库入库-开始入库-绑定仓库、行车信息-确认
     * @param moveStorageDetail 移库单明细
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDetail(MoveStorageDetail moveStorageDetail) {
        Car car = carDAO.selectById(moveStorageDetail.getCarId());
        moveStorageDetail.setState(Constant.INT_FOUR);
        moveStorageDetail.setInCarCode(car.getCode());
        moveStorageDetail.setStartInStorageTime(new Date());
        car.setState(Constant.LONG_ONE);
        carDAO.updateById(car);
        moveStorageDetailDAO.updateById(moveStorageDetail);
    }

    /**
     * 获取仓库下未被占用的库位
     * @param warehouseCode 仓库编码
     * @param factoryCode 厂区编码
     * @return String 库位编码
     */
    @Override
    public String getRecommendShelf(String warehouseCode,String factoryCode) {
        List<Shelf> storages = moveStorageDAO.getRecommendShelf(warehouseCode,factoryCode);
        List<String> strs = storages.stream().map(Shelf::getCode).collect(Collectors.toList());
        return StringUtils.join(strs, ",");
    }

    /**
     * 下拉框选择库位
     * @param pageTbl
     * @param map
     * @return PageUtils
     */
    @Override
    public PageUtils selectUnbindShelf(PageTbl pageTbl, Map<String, Object> map) {
        String sortName = pageTbl.getSortname();
        String sortOrder = pageTbl.getSortorder();
        if (StringUtils.isEmptyString(sortName)) {
            sortName = "t1.id";
        }
        if (StringUtils.isEmptyString(sortOrder)){
            sortOrder = "desc";
        }
        Page page = new Page(pageTbl.getPageno(), pageTbl.getPagesize(), sortName, "asc".equalsIgnoreCase(sortOrder));
        return new PageUtils(page.setRecords(moveStorageDAO.selectUnbindShelf(page, map)));
    }

    /**
     * 入库确认-保存
     * @param id 移库单明细主键
     * @param shelfId 库位主键
     * @param userId 用户主键
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean confirmInstorage(Long id, Long shelfId,Long userId) {
        Shelf shelf = shelfDAO.selectById(shelfId);
        moveStorageDAO.confirmInstorage(id, shelf.getCode(), userId);
        MoveStorageDetail moveStorageDetail = moveStorageDetailDAO.selectById(id);
        MoveStorage moveStorage = moveStorageDAO.selectById(moveStorageDetail.getPId());
        List<InstorageDetail> lstInstorageDetail = instorageDetailDAO.selectByMap(new HashMap<String, Object>(1) {{
            put("BATCH_NO", moveStorageDetail.getBatchNo());
        }});
    	if (lstInstorageDetail == null || lstInstorageDetail.size() == 0) {
    	    return false;
        }
    	InstorageDetail instorageDetail = lstInstorageDetail.get(0);
        try {
        	//调EBS移库接口
        	Map<String,Object> xmlMap = new HashMap<>(1);
        	xmlMap.put("line",new HashMap<String,Object>(4){{
        		put("org",instorageDetail.getOrg());
        		put("batchno",moveStorageDetail.getQaCode());
        		put("inwarehouse",moveStorageDetail.getWarehouseCode());//新仓库
        		put("inLocation",shelf.getCodeComplete());//新库位
        	}});
            interfaceDoServiceImpl.insertDo("FEWMS008", "EBS接口-调拨、移库接口", JSONObject.toJSONString(xmlMap), DateUtils.getTime(),
                    moveStorageDetail.getQaCode(),moveStorageDetail.getBatchNo(),2L, moveStorage.getMoveCode());
		} catch (Exception e) {
			e.printStackTrace();
		}
        
        MoveInStorage moveInStorage = new MoveInStorage();
        moveInStorage.setMaterialCode(moveStorageDetail.getMaterialCode());
        moveInStorage.setBatchNo(moveStorageDetail.getBatchNo());
        moveInStorage.setQaCode(moveStorageDetail.getQaCode());
        moveInStorage.setShelfCode(moveStorageDetail.getInShelfCode());
        moveInStorage.setWarehouseCode(moveStorageDetail.getWarehouseCode());
        moveInStorage.setMeter(moveStorageDetail.getMeter());
        moveInStorage.setInstorageTime(new Date());
        moveInStorage.setOrg(moveStorageDetail.getOrg());
        moveInStorage.setRfid(moveStorageDetail.getRfid());
        moveInStorage.setCarCode(moveStorageDetail.getInCarCode());
        moveInStorage.setInStorageId(userId);
        moveInStorage.setDishnumber(moveStorageDetail.getDishnumber());
        moveInStorageDAO.insert(moveInStorage);

        StorageInfo storageInfo = new StorageInfo();
        storageInfo.setMaterialCode(moveStorageDetail.getMaterialCode());
        storageInfo.setBatchNo(moveStorageDetail.getBatchNo());
        storageInfo.setQaCode(moveStorageDetail.getQaCode());
        storageInfo.setShelfCode(moveStorageDetail.getInShelfCode());
        storageInfo.setWarehouseCode(moveStorageDetail.getWarehouseCode());
        storageInfo.setMeter(moveStorageDetail.getMeter());
        storageInfo.setInStorageTime(new Date());
        storageInfo.setOrg(moveStorageDetail.getOrg());
        storageInfo.setRfid(moveStorageDetail.getRfid());
        storageInfo.setState(1);
        storageInfo.setInStorageId(userId);
        storageInfo.setDishnumber(moveStorageDetail.getDishnumber());

        //根据rfid获取到订单号、订单行号
        Map<String,Object> mapinfo=rfidBindDAO.getMaterialInfo(moveStorageDetail.getBatchNo());
        //设置订单号
        storageInfo.setOrderline(mapinfo.get("ORDERLINE")==null?"":mapinfo.get("ORDERLINE").toString());
        //设置订单行号
        storageInfo.setOrderno(mapinfo.get("ORDERNUM")==null?"":mapinfo.get("ORDERNUM").toString());
        storageInfoDAO.insert(storageInfo);
        
        /*//恢复行车状态为可用
        carDAO.updateCarByCode(moveStorageDetail.getInCarCode(),"",2L);*/

        //库位锁定
        shelfImpl.setShelfState(shelf.getCode(),moveStorage.getFactoryCode(),moveStorage.getWarehouseCode(),0);

        return true;
    }

    /**
     * 获取excel导出列表
     * @param map
     * @return List<MoveStorageDetail>
     */
    @Override
    public List<MoveStorageDetail> getMoveInExcelList(Map<String, Object> map) {
        return moveStorageDAO.getMoveInExcelList(map);
    }

    /**
     * 移库出库批量完成出库
     * @param lstIds 移库单明细主键数组
     * @param userId 用户主键
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String,Object> moveStorageOut(List<Long> lstIds, Long userId) {
        Map<String,Object> resultMap = Maps.newHashMap();

        if (lstIds == null || lstIds.size() == 0){
            resultMap.put("result", false);
            resultMap.put("msg","所选货物都已移库出库完毕，无需再次出库！");
            return resultMap;
        }

        //批量移库出库的明细
        List<MoveStorageDetail> lstMoveStorageDetail = moveStorageDetailDAO.selectBatchIds(lstIds);
        //待插入移库出库表的明细
        List<MoveOutStorage> lstMoveOutStorage = new ArrayList<>();

        List<String> lstQaCode = new ArrayList<>();
        List<String> lstCarCode = new ArrayList<>();
        List<Shelf> lstShelf = new ArrayList<>();
        List<Long> lstStorageInfoIds = new ArrayList<>();

        lstMoveStorageDetail.forEach(moveStorageDetail->{
            lstQaCode.add(moveStorageDetail.getQaCode());

            MoveStorage moveStorage = moveStorageDAO.selectById(moveStorageDetail.getPId());
            MoveOutStorage moveOutStorage = new MoveOutStorage();
            moveOutStorage.setBatchNo(moveStorageDetail.getBatchNo());
            moveOutStorage.setMaterialCode(moveStorageDetail.getMaterialCode());
            moveOutStorage.setQaCode(moveStorageDetail.getQaCode());
            moveOutStorage.setRfid(moveStorageDetail.getRfid());
            moveOutStorage.setMeter(moveStorageDetail.getMeter());
            moveOutStorage.setCarCode(moveStorageDetail.getOutCarCode());
            moveOutStorage.setOrg(moveStorageDetail.getOrg());
            moveOutStorage.setOutStorageTime(new Date());
            moveOutStorage.setWarehouseCode(moveStorage.getWarehouseCode());
            moveOutStorage.setShelfCode(moveStorageDetail.getOutShelfCode());
            moveOutStorage.setState(4);
            moveOutStorage.setDishnumber(moveStorageDetail.getDishnumber());
            lstMoveOutStorage.add(moveOutStorage);

            //行车编码
            if (StringUtils.isNotEmpty(moveStorageDetail.getOutCarCode())){
                lstCarCode.add(moveStorageDetail.getOutCarCode());
            }
            //释放库位
            List<Shelf> shelfList = shelfDAO.selectList(new EntityWrapper<Shelf>()
                    .eq("CODE", moveStorageDetail.getOutShelfCode())
                    .eq("WAREHOUSECODE", moveStorageDetail.getWarehouseCode())
                    .eq("FACTORYCODE", moveStorage.getFactoryCode()));
            if (shelfList!=null && shelfList.size()>0){
                lstShelf.add(shelfList.get(0));
            }

        });
        //批量插入移库出库表
        if (lstMoveOutStorage.size()>0){
            moveOutStorageDAO.insertMoveOutstorageBatch(lstMoveOutStorage);
        }

        //批量删除库存
        List<StorageInfo> lstStorageInfo = storageInfoDAO.selectList(new EntityWrapper<StorageInfo>().in("QACODE",lstQaCode));
        lstStorageInfo.forEach(storageInfo -> lstStorageInfoIds.add(storageInfo.getId()));
        if (lstStorageInfoIds.size()>0){
            storageInfoDAO.deleteBatchIds(lstStorageInfoIds);
        }

        //批量添加移库单明细的状态，添加移库人员
        MoveStorageDetail moveStorageDetail = new MoveStorageDetail();
        moveStorageDetail.setState(Constant.INT_THREE);
        moveStorageDetail.setOutStorageId(userId);
        moveStorageDetail.setStartOutStorageTime(new Date());
        moveStorageDetail.setOutstoragetime(new Date());
        moveStorageDetailDAO.update(moveStorageDetail,new EntityWrapper<MoveStorageDetail>().in("ID",lstIds));

        //批量设置库位可用
        lstShelf.forEach(shelf -> shelf.setState(1));
        shelfDAO.updateBatches(lstShelf);

        //批量设置行车可用
        if (lstCarCode.size()>0){
            Car car = new Car();
            car.setState(Constant.LONG_TWO);
            carDAO.update(car, new EntityWrapper<Car>().in("CODE", lstCarCode));
        }

        resultMap.put("result", true);
        resultMap.put("msg","移库出库成功！");
        return resultMap;
    }

    /**
     * 更新移库单、调拨单流水号
     * @param serial 流水号
     * @param type 类型：移库，调拨
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSerial(String serial, String type){
        moveStorageDAO.updateSerial(serial,type);
    }

    /**
     * 获取移库单今日流水号
     * @return int 流水号
     */
    @Override
    public int selectLatestAllocation(){
        return moveStorageDAO.selectLatestAllocation();
    }

}
